package f_stack

import (
	"jvmgo/jvmgo/instructions/base"
	"jvmgo/jvmgo/rtda"
)

// Duplicate the top operand stack value
// 复制顶部操作数堆栈值
type DUP struct{ base.NoOperandsInstruction }

/*
bottom -> top
[...][c][b][a]

	\_
	  |
	  V

[...][c][b][a][a]
*/
func (self *DUP) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot := stack.PopSlot()
	stack.PushSlot(slot)
	stack.PushSlot(slot)
}

// Duplicate the top operand stack value and insert two values down
// 复制顶部操作数堆栈值并向下插入两个值
type DUP_X1 struct{ base.NoOperandsInstruction }

/*
bottom -> top
[...][c][b][a]

	 __/
	|
	V

[...][c][a][b][a]
*/
func (self *DUP_X1) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot1 := stack.PopSlot()
	slot2 := stack.PopSlot()
	stack.PushSlot(slot1)
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
}

// Duplicate the top operand stack value and insert two or three values down
// 复制顶部操作数堆栈值，向下插入两个或三个值
type DUP_X2 struct{ base.NoOperandsInstruction }

/*
bottom -> top
[...][c][b][a]

	 _____/
	|
	V

[...][a][c][b][a]
*/
func (self *DUP_X2) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot1 := stack.PopSlot()
	slot2 := stack.PopSlot()
	slot3 := stack.PopSlot()
	stack.PushSlot(slot1)
	stack.PushSlot(slot3)
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
}

// Duplicate the top one or two operand stack values
// 复制顶部的一个或两个操作数堆栈值
type DUP2 struct{ base.NoOperandsInstruction }

/*
bottom -> top
[...][c][b][a]____

	\____   |
	     |  |
	     V  V

[...][c][b][a][b][a]
*/
func (self *DUP2) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot1 := stack.PopSlot()
	slot2 := stack.PopSlot()
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
}

// Duplicate the top one or two operand stack values and insert two or three values down
// 复制顶部的一个或两个操作数堆栈值，然后向下插入两个或三个值
type DUP2_X1 struct{ base.NoOperandsInstruction }

/*
bottom -> top
[...][c][b][a]

	 _/ __/
	|  |
	V  V

[...][b][a][c][b][a]
*/
func (self *DUP2_X1) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot1 := stack.PopSlot()
	slot2 := stack.PopSlot()
	slot3 := stack.PopSlot()
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
	stack.PushSlot(slot3)
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
}

// Duplicate the top one or two operand stack values and insert two, three, or four values down
// 复制顶部的一个或两个操作数堆栈值，然后向下插入两个、三个或四个值
type DUP2_X2 struct{ base.NoOperandsInstruction }

/*
bottom -> top
[...][d][c][b][a]

	 ____/ __/
	|   __/
	V  V

[...][b][a][d][c][b][a]
*/
func (self *DUP2_X2) Execute(frame *rtda.Frame) {
	stack := frame.OperandStack()
	slot1 := stack.PopSlot()
	slot2 := stack.PopSlot()
	slot3 := stack.PopSlot()
	slot4 := stack.PopSlot()
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
	stack.PushSlot(slot4)
	stack.PushSlot(slot3)
	stack.PushSlot(slot2)
	stack.PushSlot(slot1)
}
